`include "lib/defines.vh"
module ID(
    input wire clk,
    input wire rst,
    // input wire flush,
    input wire [`StallBus-1:0] stall,
    input wire ex_is_load, // EX 段是否是 load 指令
    input wire [`IF_TO_ID_WD-1:0] if_to_id_bus, // 33位，IF段传来的数据，给到ID段，包括使能信号和PC值
    input wire [31:0] inst_sram_rdata,          // 32位，指令寄存器的数据，即当前指令地址中储存的值
    input wire [`WB_TO_RF_WD-1:0] wb_to_rf_bus, // 38位，WB段传给 ID 段要写入寄存器的值
    input wire [37:0] wb_to_id,
    input wire [37:0] mem_to_id,
    input wire [37:0] ex_to_id,                 // 38位，EX段传给ID段的数据，用来判断数据相关
    input wire [65:0] hilo_ex_to_id,            // 66位，EX 传给 ID 段要写入乘除法寄存器的值


    output wire [`ID_TO_EX_WD-1:0] id_to_ex_bus,// 169位，ID 段传给 EX 段的数据
    output wire [`BR_WD-1:0] br_bus,            // 33位，ID 段传给 IF 段的数据，用来判断下一条指令的地址
    output wire stallreq_from_id                //从 ID 段发出的暂停信号
);

    reg [`IF_TO_ID_WD-1:0] if_to_id_bus_r;
    wire [31:0] inst;
    wire [31:0] id_pc;
    wire ce;
    //forwarding声明
    wire wb_rf_we;
    wire [4:0] wb_rf_waddr;
    wire [31:0] wb_rf_wdata;

    wire ex_id_we;
    wire [4:0] ex_id_waddr;
    wire [31:0] ex_id_wdata;

    wire wb_id_we;
    wire [4:0] wb_id_waddr;
    wire [31:0] wb_id_wdata;

    wire mem_id_we;
    wire [4:0] mem_id_waddr;
    wire [31:0] mem_id_wdata;
    
    reg q;

    // ID第一段： 流水线是否暂停的判断和加气泡的实现---------------------------------------------
    // ID 段会收到来自 CTRL 模块的 stall 值，而 stall 的值就是用来控制流水线的暂停的。
    //如果 stall 的值为 `Stop，那么 ID 段就会暂停，同时会将 if_to_id_bus 的值置为 0。
    // 如果 stall 的值为 `NoStop，那么 ID 段就会正常运行。
    always @ (posedge clk) begin
        if (rst) begin
            if_to_id_bus_r <= `IF_TO_ID_WD'b0;    // 33'b0 复位    
        end
        // else if (flush) begin
        //     ic_to_id_bus <= `IC_TO_ID_WD'b0;
        // end
        // 如果判断到 stall 的值的对应的 ID 段的部分是`Stop，即此刻发生了访存冲突，现在需要读取的寄存器中的值还没有获得，
        else if (stall[1]==`Stop && stall[2]==`NoStop) begin
            if_to_id_bus_r <= `IF_TO_ID_WD'b0;  // 33'b0 暂停则现在需要对流水线的 ID 段进行暂停一个周期，
                                                // 在下个周期获得到需要读取的值后再发给 ID 段
        end
        else if (stall[1]==`NoStop) begin
            if_to_id_bus_r <= if_to_id_bus; // 33'b0 正常运行
        end
    end
    
    always @(posedge clk) begin
        if (stall[1]==`Stop) begin
            q <= 1'b1;
        end
        else begin
            q <= 1'b0;
        end
    end
    //assign inst = inst_sram_rdata;
    assign inst = (q) ?inst: inst_sram_rdata; // 32位，指令寄存器的数据，即当前指令地址中储存的值
    // 这里存在问题，如果是暂停的话，应该是不应该更新的，但是这里是更新的，所以这里的逻辑存在问题
    // 但是还存在的另外一个问题就是 if_to_id_bus 是 IF 段发给 ID 段的内容,
    // 而这部分的内容是不包含指令值的， 指令的值即 inst 值是在 ID 段时根据上个
    // 周期的 IF 段中的 pc 值从内存中读取到的,是直接从内存获取的。 


    // 解包各种信号
    assign {
        ce,             // 写使能信号        
        id_pc           // 当前pc值而不是next_pc值
    } = if_to_id_bus_r;
    assign {
        wb_rf_we,       // 写使能信号
        wb_rf_waddr,    // 写地址
        wb_rf_wdata     // 写数据
    } = wb_to_rf_bus;


    assign {
        ex_id_we,       // 写使能信号
        ex_id_waddr,    // 写地址
        ex_id_wdata     // 写数据
    } = ex_to_id;

    assign {
        wb_id_we,
        wb_id_waddr,
        wb_id_wdata
    } = wb_to_id;

    assign {
        mem_id_we,
        mem_id_waddr,
        mem_id_wdata
    } = mem_to_id;

    wire [5:0] opcode;
    wire [4:0] rs,rt,rd,sa;
    wire [5:0] func;
    wire [15:0] imm;
    wire [25:0] instr_index;
    wire [4:0] base;

    wire [63:0] op_d, func_d;
    wire [31:0] rs_d, rt_d, rd_d, sa_d;

    wire [2:0] sel_alu_src1;    //sel_alu_src1 为三位宽，表示对于第一个操作数有三种来源，
    wire [3:0] sel_alu_src2;
    wire [11:0] alu_op;

    wire data_ram_en;
    wire [3:0] data_ram_wen;
    wire [3:0] data_ram_readen;//读使能信号
    
    wire rf_we;
    wire [4:0] rf_waddr;
    wire sel_rf_res;
    wire [2:0] sel_rf_dst;

    wire [31:0] rdata1, rdata2;
    wire [31:0] rdata1_af, rdata2_af;


    wire hi_r, hi_wen, lo_r, lo_wen;        // 1位控制信号
    wire [31:0] hi_data;                    // 32位 HI 寄存器数据
    wire [31:0] lo_data;                    // 32位 LO 寄存器数据
    wire [31:0] hilo_data;                  // 32位 HILO 组合数据

    assign {
        hi_wen,         // 65
        lo_wen,         // 64
        hi_data,           // 63:32
        lo_data           // 31:0
    } = hilo_ex_to_id;

    assign hi_r = inst_mfhi;    // MFHI指令产生HI寄存器读信号
    assign lo_r = inst_mflo;    // MFLO指令产生LO寄存器读信号   

    regfile u_regifle(
    	.clk    (clk            ),
        .raddr1 (rs             ),
        .rdata1 (rdata1         ),
        .raddr2 (rt             ),
        .rdata2 (rdata2         ),
        .we     (wb_rf_we       ),
        .waddr  (wb_rf_waddr    ),
        .wdata  (wb_rf_wdata    ),

        .hi_r      (hi_r        ),
        .hi_we     (hi_wen      ),
        .hi_data   (hi_data     ),
        .lo_r      (lo_r        ),
        .lo_we     (lo_wen      ),
        .lo_data   (lo_data     ),
        .hilo_data (hilo_data   )
    );// 寄存器堆，我们需要这个模块

    //1131585100ns定位错误hi_data没有定义
    wire [31:0] mf_data;
    assign mf_data = (inst_mfhi & hi_wen) ? hi_data
                    :(inst_mfhi) ? hilo_data
                    :(inst_mflo & lo_wen) ? lo_data
                    :(inst_mflo) ? hilo_data
                    :(32'b0);


    // 第二段： 正常指令的译码------------------------------------------------
    // 指令译码
    assign opcode = inst[31:26];
    assign rs = inst[25:21];
    assign rt = inst[20:16];
    assign rd = inst[15:11];
    assign sa = inst[10:6];
    assign func = inst[5:0];
    assign imm = inst[15:0]; //offset
    assign instr_index = inst[25:0];
    assign base = inst[25:21];



    wire inst_ori, inst_lui, inst_addiu, inst_beq,inst_subu,inst_jr,
        inst_jal,inst_lw,inst_or,inst_sll,inst_addu,inst_bne,inst_xor,
        inst_xori,inst_nor,inst_sw,inst_sltu,inst_slt,inst_slti,inst_sltiu,
        inst_j,inst_add,inst_addi,inst_sub,inst_and,inst_andi,inst_sllv,
        inst_sra,inst_srav,inst_srl, inst_srlv,inst_bgez,inst_bgtz,inst_blez,
        inst_bltz,inst_bltzal,inst_bgezal,inst_jalr,inst_div,inst_divu,
        inst_mflo,inst_mfhi,inst_mult,inst_multu,inst_mthi,inst_mtlo,inst_lb,
        inst_lbu,inst_lh,inst_lhu,inst_sb,inst_lsa,inst_sh;
    wire op_add, op_sub, op_slt, op_sltu;
    wire op_and, op_nor, op_or, op_xor;
    wire op_sll, op_srl, op_sra, op_lui;

    decoder_6_64 u0_decoder_6_64(
    	.in  (opcode  ),
        .out (op_d )
    );

    decoder_6_64 u1_decoder_6_64(
    	.in  (func  ),
        .out (func_d )
    );
    
    decoder_5_32 u0_decoder_5_32(
    	.in  (rs  ),
        .out (rs_d )
    );

    decoder_5_32 u1_decoder_5_32(
    	.in  (rt  ),
        .out (rt_d )
    );


    // 来源：A03_“系统能力培养大赛”MIPS指令系统规范_v1.01.pdf
    assign inst_ori     = op_d[6'b001101];                      //寄存器 rs 中的值与 0 扩展至 32 位的立即数 imm 按位逻辑或，结果写入寄存器 rt 中。
    assign inst_lui     = op_d[6'b001111];                      //将 16 位立即数 imm 写入寄存器 rt 的高 16 位，寄存器 rt 的低 16 位置 0
    assign inst_addiu   = op_d[6'b001001];                      //将寄存器 rs 的值与有符号扩展至 32 位的立即数 imm 相加，结果写入 rt 寄存器中。
    assign inst_beq     = op_d[6'b000100];                      //如果寄存器 rs 的值等于寄存器 rt 的值则转移，否则顺序执行。转移目标由立即数 offset 左移 2 位
    assign inst_subu    = op_d[6'b000000] && func_d[6'b100011]; //将寄存器 rs 的值与寄存器 rt 的值相减，结果写入 rd 寄存器中
    assign inst_jr      = op_d[6'b000000] && func_d[6'b001000]; // 无条件跳转。跳转目标为寄存器 rs 中的值
    assign inst_jal     = op_d[6'b000011];                      //无条件跳转。跳转目标由该分支指令对应的延迟槽指令的 PC 的最高 4 位与立即数 instr_index 左移2 位后的值拼接得到。同时将该分支对应延迟槽指令之后的指令的 PC 值保存至第 31 号通用寄存器中
    assign inst_lw      = op_d[6'b100011];                      //将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址，如果地址不是 4 的整数倍则触发地址错例外，否则据此虚地址从存储器中读取连续 4 个字节的值，写入到 rt 寄存器中。
    assign inst_addu    = op_d[6'b000000] && func_d[6'b100001]; //将寄存器 rs 的值与寄存器 rt 的值相加，结果写入 rd 寄存器中
    assign inst_or      = op_d[6'b000000] && func_d[6'b100101]; //寄存器 rs 中的值与寄存器 rt 中的值按位逻辑或，结果写入寄存器 rd 中
    assign inst_sll     = op_d[6'b000000] && func_d[6'b000000]; //由立即数 sa 指定移位量，对寄存器 rt 的值进行逻辑左移，结果写入寄存器 rd 中。
    assign inst_bne     = op_d[6'b000101];                      //如果寄存器 rs 的值不等于寄存器 rt 的值则转移，否则顺序执行。转移目标由立即数 offset 左移 2位并进行有符号扩展的值加上该分支指令对应的延迟槽指令的 PC 计算得到
    assign inst_xor     = op_d[6'b000000] && func_d[6'b100110]; //寄存器 rs 中的值与寄存器 rt 中的值按位逻辑异或，结果写入寄存器 rd 中。
    assign inst_xori    = op_d[6'b001110];                      //寄存器 rs 中的值与 0 扩展至 32 位的立即数 imm 按位逻辑异或，结果写入寄存器 rt 中。
    assign inst_nor     = op_d[6'b000000] && func_d[6'b100111]; //寄存器 rs 中的值与寄存器 rt 中的值按位逻辑或非，结果写入寄存器 rd 中。
    assign inst_sw      = op_d[6'b101011];                      //将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址，如果地址不是 4 的整数倍则触发地址错例外，否则据此虚地址将 rt 寄存器存入存储器中。
    assign inst_sltu    = op_d[6'b000000] && func_d[6'b101011]; //将寄存器 rs 的值与寄存器 rt 中的值进行无符号数比较，如果寄存器 rs 中的值小，则寄存器 rd 置 1；否则寄存器 rd 置 0。
    assign inst_slt     = op_d[6'b000000] && func_d[6'b101010]; //将寄存器 rs 的值与寄存器 rt 中的值进行有符号数比较，如果寄存器 rs 中的值小，则寄存器 rd 置 1；否则寄存器 rd 置 0。
    assign inst_slti    = op_d[6'b001010];                      //将寄存器 rs 的值与有符号扩展至 32 位的立即数 imm 进行有符号数比较，如果寄存器 rs 中的值小，则寄存器 rt 置 1；否则寄存器 rt 置 0。
    assign inst_sltiu   = op_d[6'b001011];                      //将寄存器 rs 的值与有符号扩展至 32 位的立即数 imm 进行无符号数比较，如果寄存器 rs 中的值小，则寄存器 rt 置 1；否则寄存器 rt 置 0。
    assign inst_j       = op_d[6'b000010];                      //无条件跳转。跳转目标由该分支指令对应的延迟槽指令的 PC 的最高 4 位与立即数 instr_index 左移2 位后的值拼接得到。
    assign inst_add     = op_d[6'b000000] && func_d[6'b10_0000];//将寄存器 rs 的值与寄存器 rt 的值相加，结果写入寄存器 rd 中。如果产生溢出，则触发整型溢出例外（IntegerOverflow）。
    assign inst_addi    = op_d[6'b001000];                      //将寄存器 rs 的值与有符号扩展至 32 位的立即数 imm 相加，结果写入 rt 寄存器中。如果产生溢出，则触发整型溢出例外（IntegerOverflow）。
    assign inst_sub     = op_d[6'b000000] && func_d[6'b100010]; //将寄存器 rs 的值与寄存器 rt 的值相减，结果写入 rd 寄存器中。如果产生溢出，则触发整型溢出例外（IntegerOverflow）。
    assign inst_and     = op_d[6'b000000] && func_d[6'b100100]; //寄存器 rs 中的值与寄存器 rt 中的值按位逻辑与，结果写入寄存器 rd 中。
    assign inst_andi    = op_d[6'b001100];                      //寄存器 rs 中的值与 0 扩展至 32 位的立即数 imm 按位逻辑与，结果写入寄存器 rt 中。
    assign inst_sllv    = op_d[6'b000000] && func_d[6'b000100]; //由寄存器 rs 中的值指定移位量，对寄存器 rt 的值进行逻辑左移，结果写入寄存器 rd 中。
    assign inst_sra     = op_d[6'b000000] && func_d[6'b000011]; //由立即数 sa 指定移位量，对寄存器 rt 的值进行算术右移，结果写入寄存器 rd 中。
    assign inst_srav    = op_d[6'b000000] && func_d[6'b000111]; //由寄存器 rs 中的值指定移位量，对寄存器 rt 的值进行算术右移，结果写入寄存器 rd 中。
    assign inst_srl     = op_d[6'b000000] && func_d[6'b000010]; //由立即数 sa 指定移位量，对寄存器 rt 的值进行逻辑右移，结果写入寄存器 rd 中。
    assign inst_srlv    = op_d[6'b000000] && func_d[6'b000110]; //由寄存器 rs 中的值指定移位量，对寄存器 rt 的值进行逻辑右移，结果写入寄存器 rd 中。
    assign inst_bgez    = op_d[6'b000001] && rt_d[5'b00001];    //如果寄存器 rs 的值大于等于 0 则转移，否则顺序执行。转移目标由立即数 offset 左移 2 位并进行有符号扩展的值加上该分支指令对应的延迟槽指令的 PC 计算得到。
    assign inst_bgtz    = op_d[6'b000111] && rt_d[5'b00000];    //如果寄存器 rs 的值大于 0 则转移，否则顺序执行。转移目标由立即数 offset 左移 2 位并进行有符号扩展的值加上该分支指令对应的延迟槽指令的 PC 计算得到。
    assign inst_blez    = op_d[6'b000110] && rt_d[5'b00000];    //如果寄存器 rs 的值小于等于 0 则转移，否则顺序执行。转移目标由立即数 offset 左移 2 位并进行有符号符号扩展的值加上该分支指令对应的延迟槽指令的 PC 计算得到。
    assign inst_bltz    = op_d[6'b000001] && rt_d[5'b00000];    //如果寄存器 rs 的值小于 0 则转移，否则顺序执行。转移目标由立即数 offset 左移 2 位并进行有符号扩展的值加上该分支指令对应的延迟槽指令的 PC 计算得到。
    assign inst_bltzal  = op_d[6'b000001] && rt_d[5'b10000];    //如果寄存器 rs 的值小于 0 则转移，否则顺序执行。转移目标由立即数 offset 左移 2 位并进行有符号指令之后的指令的 PC 值保存至第 31 号通用寄存器中。
    assign inst_bgezal  = op_d[6'b000001] && rt_d[5'b10001];    //如果寄存器 rs 的值大于等于 0 则转移，否则顺序执行。转移目标由立即数 offset 左移 2 位并进行有....这个根本就没有
    assign inst_jalr    = op_d[6'b000000] && func_d[6'b001001]; //无条件跳转。跳转目标为寄存器 rs 中的值同时将该分支对应延迟槽指令之后的指令的 PC 值保存至寄存器 rd 中。
    assign inst_div     = op_d[6'b000000] && func_d[6'b011010]; //有符号除法，将寄存器 rs 的值除以寄存器 rt 的值，商写入 LO 寄存器，余数写入 HI 寄存器
    assign inst_divu    = op_d[6'b000000] && func_d[6'b011011]; //无符号除法，将寄存器 rs 的值除以寄存器 rt 的值，商写入 LO 寄存器，余数写入 HI 寄存器
    assign inst_mflo    = op_d[6'b000000] && func_d[6'b010010]; //将 LO 寄存器的值写入到寄存器 rd 中
    assign inst_mfhi    = op_d[6'b000000] && func_d[6'b010000]; //将 HI 寄存器的值写入到寄存器 rd 中
    assign inst_mult    = op_d[6'b000000] && func_d[6'b011000]; //有符号乘法，将寄存器 rs 的值与寄存器 rt 的值相乘，结果的低 32 位写入 LO 寄存器，结果的高 32 位写入 HI 寄存器
    assign inst_multu   = op_d[6'b000000] && func_d[6'b011001]; //无符号乘法，将寄存器 rs 的值与寄存器 rt 的值相乘，结果的低 32 位写入 LO 寄存器，结果的高 32 位写入 HI 寄存器
    assign inst_mthi    = op_d[6'b000000] && func_d[6'b010001]; //将寄存器 rs 的值写入到 HI 寄存器中
    assign inst_mtlo    = op_d[6'b000000] && func_d[6'b010011]; //将寄存器 rs 的值写入到 LO 寄存器中
    assign inst_lb      = op_d[6'b100000];                      //将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址，据此虚地址从存储器中读取 1 个字节的值并进行符号扩展，写入到 rt 寄存器中
    assign inst_lbu     = op_d[6'b100100];                      //将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址，据此虚地址从存储器中读取 1 个字节的值并进行 0 扩展，写入到 rt 寄存器中
    assign inst_lh      = op_d[6'b100001];                      //将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址，如果地址不是 2 的整数倍则触发地址错例外，否则据此虚地址从存储器中读取连续 2 个字节的值并进行符号扩展，写入到rt 寄存器中。
    assign inst_lhu     = op_d[6'b100101];                      //将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址，如果地址不是 2 的整数倍则触发地址错例外，否则据此虚地址从存储器中读取连续 2 个字节的值并进行 0 扩展，写入到 rt寄存器中。
    assign inst_sb      = op_d[6'b101000];                      //将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址，据此虚地址将 rt 寄存器的最低字节存入存储器中。
    assign inst_sh      = op_d[6'b101001];                      //将 base 寄存器的值加上符号扩展后的立即数 offset 得到访存的虚地址，如果地址不是 2 的整数倍则触发地址错例外，否则据此虚地址将 rt 寄存器的低半字存入存储器中。
    assign inst_lsa     = op_d[6'b011100] && func_d[6'b11_0111];//将寄存器 rs 的值左移 sa 位，结果写入寄存器 rd 中，根本就没有这条指令



    // 第三阶段： 设置操作数来源---------------------------------------------




    // 第一个操作数有三种来源，
    // 第一种：第一个操作数的值为 rs 寄存器的值，
    // 第二种：当前的 PC 值，
    // 第三种：立即数零扩展
    // rs to reg1(补充)
    assign sel_alu_src1[0] = inst_sh | inst_sb | inst_lhu | inst_lh | inst_lbu | inst_bgez | 
            inst_srlv | inst_srav | inst_sllv | inst_andi | inst_and | inst_sub | inst_addi | inst_add | 
            inst_sltiu | inst_slti | inst_slt | inst_sltu | inst_sw | inst_nor | inst_xori | inst_xor | 
            inst_ori | inst_addiu | inst_subu | inst_jr | inst_lw | inst_addu | 
            inst_or   | inst_mflo  |inst_mfhi | inst_lb |inst_lsa;

    // pc to reg1*(补充)
    assign sel_alu_src1[1] = inst_jal | inst_bltzal | inst_bgezal |inst_jalr;

    // sa_zero_extend to reg1(补充)
    assign sel_alu_src1[2] = inst_srl |inst_sra | inst_sll;

    // 第二个操作数有四种来源，
    // 第一种：第二个操作数的值为 rs 寄存器的值，
    // 第二种 rs的值为立即数符号扩展，
    // 第三种，将第二个操作数复制为 32'b8，只有个别指令可以用的到，
    // 第四种，第二个操作数的值为立即数零扩展。
    // rt to reg2(补充)
    assign sel_alu_src2[0] = inst_lsa|inst_mfhi|inst_mflo | inst_srl | inst_srlv | inst_srav | inst_sra | inst_sllv | inst_and | inst_sub | inst_add | inst_slt | inst_sltu | inst_nor | inst_xor  | inst_subu | inst_addu | inst_or | inst_sll |inst_div | inst_divu;
    
    // imm_sign_extend to reg2(补充)
    assign sel_alu_src2[1] = inst_sh | inst_sb | inst_lhu | inst_lh | inst_lbu | inst_addi | inst_sltiu | inst_slti | inst_sw | inst_lui | inst_addiu | inst_lw |inst_lb;

    // 32'b8 to reg2(补充)
    assign sel_alu_src2[2] = inst_jal | inst_bltzal | inst_bgezal |inst_jalr;

    // imm_zero_extend to reg2(补充)
    assign sel_alu_src2[3] = inst_andi | inst_xori | inst_ori;


    //将读取的指令导入op
    assign op_add =inst_lsa|inst_sh | inst_sb | inst_lhu | inst_lh | inst_lbu |  inst_lb | inst_addi | inst_add | inst_addiu | inst_lw | inst_addu | inst_jal | inst_sw | inst_bltzal |inst_bgezal|inst_jalr;
    assign op_sub =inst_sub | inst_subu;
    assign op_slt = inst_slt | inst_slti; //有符号比较
    assign op_sltu = inst_sltu|inst_sltiu;  //无符号比较
    assign op_and = inst_andi | inst_and | inst_mflo |inst_mfhi;
    assign op_nor = inst_nor;
    assign op_or = inst_ori | inst_or;
    assign op_xor = inst_xori |inst_xor;
    assign op_sll = inst_sllv | inst_sll;//逻辑左移
    assign op_srl = inst_srl | inst_srlv;//逻辑右移
    assign op_sra = inst_srav | inst_sra;//算术右移
    assign op_lui = inst_lui;

    assign alu_op = {op_add, op_sub, op_slt, op_sltu,
                     op_and, op_nor, op_or, op_xor,
                     op_sll, op_srl, op_sra, op_lui};



    // load and store enable（进行补充）
    assign data_ram_en =inst_sh | inst_sb | inst_lhu | inst_lh | inst_lbu | inst_lw | inst_sw | inst_lb;

    // write enable（补充）
    assign data_ram_wen = inst_sw ? 4'b1111 : 4'b0000;


    // 读使能信号
    assign data_ram_readen =  inst_lw  ? 4'b1111 
                             :inst_lb  ? 4'b0001 
                             :inst_lbu ? 4'b0010
                             :inst_lh  ? 4'b0011
                             :inst_lhu ? 4'b0100
                             :inst_sb  ? 4'b0101
                             :inst_sh  ? 4'b0111
                             :4'b0000;


    // regfile store enable（补充）
    // 只要有写操作就为1
   assign rf_we =inst_lsa|inst_lhu | inst_lh | inst_lbu | inst_lb| inst_mfhi | inst_mflo | inst_jalr |inst_bgezal | inst_bltzal|inst_srl | inst_srlv | inst_srav | inst_sra | inst_sllv | inst_andi | inst_and | inst_sub | inst_addi | inst_add | inst_sltiu | inst_slti | inst_slt | inst_sltu | inst_nor |inst_xori | inst_xor | inst_sll | inst_ori | inst_lui | inst_addiu | inst_subu | inst_jal | inst_lw | inst_addu | inst_or;


    // store in [rd]（补充）
    assign sel_rf_dst[0] = inst_lsa|inst_mfhi | inst_mflo | inst_jalr |inst_srl | inst_srlv | inst_srav | inst_sra | inst_sllv | inst_and | inst_sub | inst_add | inst_slt | inst_sltu | inst_nor | inst_xor | inst_subu | inst_addu | inst_or | inst_sll;
    // store in [rt] （补充）
    assign sel_rf_dst[1] = inst_lhu | inst_lh | inst_lbu | inst_lb |inst_andi | inst_addi | inst_sltiu | inst_slti | inst_xori | inst_ori | inst_lui | inst_addiu | inst_lw;
    // store in [31]（补充）
    assign sel_rf_dst[2] = inst_jal | inst_bltzal | inst_bgezal;

    // sel for regfile address
    assign rf_waddr = {5{sel_rf_dst[0]}} & rd 
                    | {5{sel_rf_dst[1]}} & rt
                    | {5{sel_rf_dst[2]}} & 5'b11111;

    // 0 from alu_res ; 1 from ld_res
    assign sel_rf_res = 1'b0; 
    //错误定位：113158500ns时mf_data没有定义
    assign rdata1_af = 
    (inst_mfhi | inst_mflo) ? mf_data
                   : (ex_id_we &(ex_id_waddr==rs))?ex_id_wdata
                   : (mem_id_we &(mem_id_waddr==rs)) ? mem_id_wdata
                   : (wb_id_we &(wb_id_waddr==rs)) ? wb_id_wdata 
                   : rdata1;
    assign rdata2_af = 
    (inst_mfhi | inst_mflo) ? mf_data
                   : (ex_id_we &(ex_id_waddr==rt))?ex_id_wdata
                   : (mem_id_we &(mem_id_waddr==rt)) ? mem_id_wdata
                   : (wb_id_we &(wb_id_waddr==rt)) ? wb_id_wdata 
                   : rdata2;
    //对 rdata1_af 进行位移操作
    wire [31:0] rdata1_final;
    assign rdata1_final = (inst_lsa &inst[7:6]==2'b11) ? {rdata1_af[27:0] ,4'b0}
                    :(inst_lsa & inst[7:6]==2'b10) ? {rdata1_af[28:0] ,3'b0}
                    :(inst_lsa & inst[7:6]==2'b01) ? {rdata1_af[29:0] ,2'b0}
                    :(inst_lsa & inst[7:6]==2'b00) ? {rdata1_af[30:0] ,1'b0}
                    :rdata1_af;

    // 第四段：传值给其他阶段。---------------------------------------------
    assign id_to_ex_bus = {
        inst_mthi,      // 165
        inst_mtlo,      // 164
        inst_multu,     // 163
        inst_mult,      // 162
        inst_divu,      // 161
        inst_div,       // 160
        id_pc,          // 159:128
        inst,           // 127:96
        alu_op,         // 95:84
        sel_alu_src1,   // 83:81
        sel_alu_src2,   // 80:77
        data_ram_en,    // 76
        data_ram_wen,   // 75:72
        data_ram_readen,// 71
        rf_we,          // 70
        rf_waddr,       // 69:65
        sel_rf_res,     // 64
        rdata1_af,   // 63:32
        rdata2_af       // 31:0
    };


    wire br_e;
    wire [31:0] br_addr;
    wire rs_eq_rt;
    wire rs_ge_z;
    wire rs_gt_z;
    wire rs_le_z;
    wire rs_lt_z;
    wire [31:0] pc_plus_4;
    assign pc_plus_4 = id_pc + 32'h4;

    //寄存器值与零的比较
    assign rs_ge_z  = (rdata1_af[31] == 1'b0); //大于等于0
    assign rs_gt_z  = (rdata1_af[31] == 1'b0 & rdata1_af != 32'b0  );  //大于0
    assign rs_le_z  = (rdata1_af[31] == 1'b1 | rdata1_af == 32'b0  );  //小于等于0
    assign rs_lt_z  = (rdata1_af[31] == 1'b1);  //小于0

    assign rs_eq_rt = (rdata1_af == rdata2_af);

    //跳转指令相关
    assign br_e = inst_jalr | (inst_bgezal & rs_ge_z ) | ( inst_bltzal & rs_lt_z) | (inst_bgtz & rs_gt_z  ) | (inst_bltz & rs_lt_z) | (inst_blez & rs_le_z) | (inst_bgez & rs_ge_z ) | (inst_beq & rs_eq_rt) | inst_jr | inst_jal | (inst_bne & !rs_eq_rt) | inst_j ;
    assign br_addr = inst_beq ? (pc_plus_4 + {{14{inst[15]}},inst[15:0],2'b0}) 
                    :(inst_jr |inst_jalr)  ? (rdata1_af)  
                    : inst_jal ? ({pc_plus_4[31:28],inst[25:0],2'b0}) 
                    : inst_j ? ({pc_plus_4[31:28],inst[25:0],2'b0}) 
                    :(inst_bgezal|inst_bltzal |inst_blez | inst_bltz |inst_bgez |inst_bgtz ) ? (pc_plus_4 + {{14{inst[15]}},inst[15:0],2'b00})
                    :inst_bne ? (pc_plus_4 + {{14{inst[15]}},{inst[15:0],2'b00}}) : 32'b0;


    assign br_bus = {
        br_e,
        br_addr
    };

    assign stallreq_from_id = (ex_is_load  & ex_id_waddr == rs) | (ex_is_load & ex_id_waddr == rt) ; // 从 ID 段发出的暂停信号
    


endmodule